
#pragma once 

#include <vtkm/worklet/internal/WorkletBase.h>

#include <vtkm/cont/arg/ControlSignatureTagBase.h>
#include <vtkm/cont/arg/TransportTagArrayIn.h>
#include <vtkm/cont/arg/TransportTagArrayOut.h>

#include <vtkm/exec/arg/FetchTagArrayDirectIn.h>
#include <vtkm/exec/arg/FetchTagArrayDirectOut.h>

#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleGroupVec.h>
#include <vtkm/cont/arg/TypeCheck.h>
#include <vtkm/TypeList.h>
#include <vtkm/ListTag.h>

using vtkm::cont::arg::TypeCheck;

struct TypeCheckTagVariables
{
};

template<typename ArrayType>
struct TypeCheck<TypeCheckTagVariables, ArrayType>
{
	static constexpr bool value = false;
};

template<typename T, typename Storage>
struct TypeCheck<TypeCheckTagVariables, vtkm::cont::ArrayHandle<T, Storage>>
{
	static constexpr bool value = vtkm::ListContains<vtkm::TypeListFieldScalar, T>::value;
};


#include <vtkm/cont/arg/Transport.h>
using vtkm::cont::arg::Transport;


template<vtkm::IdComponent NumVariables>
struct TransportTagVariables
{
};


template<
	vtkm::IdComponent NumVariables,
	typename ContObjectType,
	typename Device>
	struct Transport<
	TransportTagVariables<NumVariables>,
	ContObjectType,
	Device>
{
	VTKM_IS_ARRAY_HANDLE(ContObjectType);
	using GroupedArrayType = vtkm::cont::ArrayHandleGroupVec<ContObjectType, NumVariables>;

	using ExecObjectType = typename GroupedArrayType::template ExecutionTypes<Device>::Portal;

	template<typename InputDomainType>
	VTKM_CONT ExecObjectType operator()
		(const ContObjectType& obj,
			const InputDomainType&,
			const vtkm::Id inputRange,
			const vtkm::Id outputRange,
			vtkm::cont::Token& token) const
	{
		GroupedArrayType groupedArray(obj);
		return groupedArray.PrepareForOutput(outputRange, Device());
	}
};